<!--
    Mango - Open Source M2M - http://mango.serotoninsoftware.com
    Copyright (C) 2006-2011 Serotonin Software Technologies Inc.
    @auteur Matthew Lohbihler
    
    Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier
    aux termes de la licence publique générale GNU telle que publiée par
    la Free Software Foundation, soit la version 3 de la licence, ou
    (à votre choix) toute version ultérieure.

    Ce programme est distribué dans l'espoir qu'il sera utile,
    mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de
    la qualité marchande ou l'adéquation à un usage particulier.  Voir le
    Licence publique générale GNU pour plus de détails.

    Vous devriez avoir reçu une copie de la licence publique générale de GNU
    en même temps que ce programme.  Si ce n'est pas le cas, voir http://www.gnu.org/licenses/.
 -->
<h1>Vue d'ensemble</h1>
<p>Les points Meta sont configurés en créant un "contexte" de points existants, ils deviennent accessible après l'exécution d'un script. Les points de ce contexte peuvent être n'importe quel point existants, y compris le point en cours d'édition. (Le point actuel doit être enregistré pour apparaître dans liste de points</p>

<h1>Configuration du point</h1>
<p><b>Type de donnée</b> détermines the type qui sera renvoyé par le script. </p>
<p><b>Contexte script</b> définit les points nécessaire pour l'exécution du script. A chaque point ajouté est affecté un champ <b>Var</b>, qui sera le nom de la variable du point dans le script.
 Ces noms de variables doivent être conformes au nom de variable ECMAScript: Elle doivent par une lettre ou trait de soulignement, et ne doivent pas contenir d'espace. D'autres contraintes peuvent s'appliquer. Vous recevrez des validation ou exception d'exécution du script si les variables ne sont pas correctement définies. Pour ajouter un point au contexte, sélectionnez le dans la liste et cliquez sur l'icône <img src="images/add.png"/>. Pour supprimer un point cliquez sur l'icône associé au point <img src="images/bullet_delete.png"/> .
 Les points inutiles ne doivent pas être ajoutés au contexte car cela entrainera une consommation de mémoire supplémentaire dans la préparation des données.
 Des variables inutiles peuvent provoquer l'exécution involontaire de script. (Voir "exécution de script " ci-dessous.) 
 Parfois, il peut être utile d'inclure une variable script dans le contexte afin de déclencher l'exécution d'un script.</p>

<h1>Scripts</h1>
<p>La fenêtre <b>Script</b> est l'espace ou sont écrit les scripts à exécuter. Les scripts doivent être conformes à la norme ECMAScript, et <b>doivent toujours retourner une valeur</b>. Exemple de script élémentaire:</p>
<pre>return x.value;</pre>
<p>... x est le nom d'une variable définie dans le contexte du script. La valeur retournée est simplement la valeur actuelle du point auquel 'x' fait référence. Les fonctions mathématiques typiques peuvent être utilisées. Exemple plus complexe:</p>
<pre>return Math.sqrt(x.value * 3);</pre>
<p>Cela renvoie la racine carrée de la valeur du 'x' multipliée par 3. (Note: l'objet Math est définei par JavaScript. consultez la documentation ECMAScript pour plus d'informations.) Des scripts complexes peuvent être écrits incluant des variables locales, des boucles, et des expressions logiques. Par exemple:</p>
<pre>var t = x.value + y.value;
if (b.value) {
    for (var i=0; i&lt;5; i++) {
        tmp += x.value - y.value;
    }
}
else {
    tmp = -tmp;
}
return tmp;</pre>
<p>Ce qui précède n'est pas destiné à calculer une valeur utile mais plutôt de démontrer le potentiel des scripts complexes.</p>
<p>En complément du contexte ECMAScript, Scada-LTS peut aussi comporter des fonctions globales utiles y compris max(), min(), avg(), et sum(). (Ces fonctions sont implémentées dans un fichier de script situé dans  WEB-INF/scripts/scriptFunctions.js. Ce fichier peut être modifié ou amélioré en ajoutant si nécessaire vos propres fonctions globales. Ce fichier est chargé au démarrage de Scada-LTS, chaque modification demande donc un redémarrage pour être prise en compte.) Pour les utiliser, il suffit de les appeler à partir de votre script, par exemple:</p>
<pre>return max(x.value, y.value, z.value);</pre>
<p>Ceci renvoie les valeurs maximales des valeurs actuelles 'x', 'y', et 'z'. N'importe quel nombre de paramètres peuvent être donnés à ces fonctions globales.</p>
<p>Une fois le script écrit, cliquez sur l'icône <img src="images/accept.png"/> pour l'exécuter et tenter de calculer le résultat.</p>

<h1>Valeurs de temps</h1>
<p>On peut aussi utiliser le timestamp de la dernière valeur dans le script. Les champs suivants sont utilisables:</p>
<dl>
  <dt>p.time</dt>
  <dd>retourne le timestamp de la valeur en milliseconde à partir de la date de référence 01/01/1970 à 00:00:00</dd>
  <dt>p.millis</dt>
  <dd>0-999 milliseconde de p.time</dd>
  <dt>p.second</dt>
  <dd>0-60</dd>
  <dt>p.minute</dt>
  <dd>0-60</dd>
  <dt>p.hour</dt>
  <dd>0-23</dd>
  <dt>p.day</dt>
  <dd>1-28,31</dd>
  <dt>p.dayOfWeek</dt>
  <dd>1-7 ou 1 correspond au dimanche</dd>
  <dt>p.dayOfYear</dt>
  <dd>1-365,366</dd>
  <dt>p.month</dt>
  <dd>1-12</dd>
  <dt>p.year</dt>
  <dd>sur 4 digits</dd>
</dl>
<p>
  Pour définir explicitement le timestamp d'une valeur, Déclarez la variable TIMESTAMP du contexte avant l'instruction return. La valeur de cette variable  
  doit être en milliseconde par rapport à la date de référence 01/01/1970 00:00:00 UTC. Par exemple:
</p>
<pre>TIMESTAMP = new Date().getTime();
return p.value + 1;
</pre>

<h1>Objets contexte</h1>
<p>Dans la terminologie JavaScript la variable var est en réalité un objet. Un objet est un conteneur de valeurs et fonctions qui peuvent être référencées par les noms de propriété. Pour obtenir la descriptions des propriétés disponibles pour une utilisation dans un script, utilisez la propriété help , e.g.:</p>
<pre>return x.help;</pre>
<p>Ce script est plus efficace pour les données de type alphanumerique, mais ce n'est pas obligatoire. La propriété help property est identique à la fonction toString(), qui est disponible pour tous les objets du contexte et pas seulement dans les variables du script.</p>
<p>La propriété de la <b>valeur</b> est la valeur actuelle du point. Le type de la valeur JavaScript est identique au type de Scada-LTS: Binaire devient booléen, Numerique devient flottant, Multi-états devient entier, et Alphanumerique devient chaine.</p>
<p>Chaque variable de script implémente aussi 4 fonctions. Les objets retournés par ces fonctions dépendent du type de donnée du point auquel se réfere la variable. Encore une fois, la propriété help peut être utilisé pour obtenir la description de l'objet retourné. Pour le paramètre "periodType" de toutes les fonctions ci-dessous, les variables globales pré-definies suivantes peuvent être utilisées: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, et YEAR.</p>
<p>La fonction <b>ago()</b> retourne la valeur du point à un instant passé. Par exemple, l'appel "x.ago(HOUR, 3)" retourne la valeur qu'avait le point exactement 3 heures auparavant.</p>
<p>La fonction <b>past()</b> retourne un object contenant des statistiques sur une période maintenant terminée. Ci-dessous une description des divers objets statistiques.</p>
<p>Les fonctions <b>prev()</b> et <b>previous()</b> sont identiques; la dernière est fournie pour une plus grande facilité linguistique. Les fonctions retournent le même objet statistique que past(), mais sur une plage de temps différente. Les débuts et fin de périodes sont définies pour correspondre au type de période. Par exemple, si la période est de type HOURLY et égale à 1, et si la fonction est lancée à 18:05, le laps de temps utilisé sera de 17:00 (inclus) à 18:00 (exclus). Pour une période de 3,ce serait de 15:00 à 18:00.
 Egalement, MONTH commence à minuit le premier jour du mois précédent et se termine le dernier jour du mois précédent (pour les périodes = à 1). Les autres périodes fonctionnes de la même façon. WEEK commence le lundi à minuit conformément aux standards de la norme ISO.</p>

<h1>Objets statistiques</h1>
<p>Les objets statistiques sont retournés par les fonctions past(), prev(), et previous(). (voir "Objets contexte" ci-dessus.) Les propriétés des objets retournés dépendent du type de donnée du point à partir duquel ils sont générés. Les valeurs de temps des objects sont stockés comme des entiers, mais représentent le nombre de milliseconde depuis le 1 Jan 1970 minuit.</p>
<p>
  L'objet <b>AnalogStatistics</b> est retourné par des points Numeriques. Il contient les propriétés suivantes:
</p>
<ul>
  <li><b>minimum</b>: (flottant) la valeur minimale du point atteint pendant la période</li>
  <li><b>minimum time</b>: (entier) l'heure à laquelle la valeur minimum a été atteinte</li>
  <li><b>maximum</b>: (flottant) la valeur maximale du point atteint pendant la période</li>
  <li><b>maximum time</b>: (entier) l'heure à laquelle la valeur maximale a été atteinte</li>
  <li><b>average</b>: (flottant) la valeur moyenne du point pendant la période</li>
  <li><b>sum</b>: (flottant) Somme detoutes les mise à jour de valeur durant la période (utile pour un comptage de pulsations)</li>
  <li><b>count</b>: (Entier) le nombre de tmise à jour durant la période</li>
  <li><b>noData</b>: (booléen) Si la période contenait aucune donnée (true si la période précède la première valeur connue du point)</li>
  <li><b>realStart</b>: (Entier) L'heure réelle de début utilisée dans les calculs (au cas ou l'heure de début précède la première valeur connue du point)</li>
  <li><b>end</b>: (entier) L'heure de fin utilisée dans les calculs</li>
</ul>
<p>
  Par exemple, le script suivant retourne la valeur minimum de 'n' de la dernière heure:
</p>
<pre>return n.past(HOUR).minimum;</pre>

<p>
  L'objet <b>StartsAndRuntimeList</b> object est retourné par les points binaires et multi-états. Il contient les propriétés suivantes:
</p>
<ul>
  <li><b>realStart</b>: (entier) L'heure réelle de début utilisée dans les calculs (au cas ou l'heure de début précède la première valeur connue du point)</li>
  <li><b>end</b>: (entier) L'heure de fin utilisée dans les calculs</li>
  <li><b>data</b>: (array) la liste des objets StartAndRuntime individuels.</li>
</ul>
<p>Chaque objet StartAndRuntime a les propriétés suivantes:
</p>
<ul>
  <li><b>value</b>: (bouléen pour binaire, entier pour multi-états) Etat du point pour lequel s'applique les propriétés suivantes</li>
  <li><b>starts</b>: (entier) Le nombre de fois que l'état a été atteint pendant la période</li>
  <li><b>runtime</b>: (entier) La durée en millisecondes pendant laquelle le point était dans l'état</li>
  <li><b>proportion</b>: (float) La proportion de la périod durant laquelle le point était dans l'état (runtime / real duration)</li>
  <li><b>percentage</b>: (float) proportion * 100</li>
</ul>

<p>
  Pour accéder à un objet spécifique StartAndRuntime de la liste, utilisez la fonction get(). Par exemple, la ligne suivante retourne la proportion de temps pour laquelle 'b' était à l'état 'false' durant les 2 mois précédents.
</p>
<pre>return b.past(MONTH, 2).get(false).proportion;</pre>

<p>L'objet <b>ValueChangeCounter</b> est retourné par des points Alphanumerique. Il possede la propriété unique <b>changes</b>, qui est le nombre de changement du point pendant la période. Par exemple, la ligne suivante retourne le nombre de changement 'b' dans les 45 dernières minutese number of times.
</p>
<pre>return b.previous(MINUTE, 45);</pre>

<p>Pour plus de commodités, si un objet var script est retourné par un script, c'est sa valeur actuelle qui sera utilisée. Ainsi, le script suivant retournera la valeur actuelle de 'x':</p>
<pre>return x;</pre>
<p>Cependant, le script ne retournera pas la somme de 'x' et 'y':</p>
<pre>return x + y;</pre>
<p>... Il faudrait pour ce script:</p>
<pre>return x.value + y.value;</pre>

<h1>Exécution de scripts</h1>
<p>Chaque fois qu'un script est exécuté à partir d'un point, le résultat est affecté au point comme une valeur de mise à jour. Le temps (la date ?) d'exécution d'un script peut être contrôlé avec la valeur <b>Update event</b>. Le paramètre "Context update" déclenche le script à chaque mise à jour d'un point du contexte. Les autres paramètres déclenche l'exécution du script à une date prévue.</p>
<p>Le paramètre <b>Délai d'exécution</b> peut être renseigné pour empêcher l'exécution multiple et non désirée d'un script. En général plusieurs points interviennent dans un contexte, Si vous utilisez l'option "Mise à jour contexte" l'exécution du script se lancera achaque fois qu'un point du contexte est mis à jour. De même si les déclenchement du script est basé sur le temps, le script risque de s'exécuter avant la mise à jour des points, et retourner des résultats tendancieux. Le retard d'exécution de script peut apporter des résultats plus fiables. Si vous utilsez "Mise à jour contexte" pour l'exécution,  le script se lancera x secondes après la dernière mise à jour d'un point du contexte. Pour une exécution basée sur le temps, le script se lancera x secondes après l'évènement défini.</p>
<p>Le param&egrave;tre <b>Context change</b> entraîne l'ex&egrave;cution du script chaque fois qu'un point dans son contexte est modifi&egrave;. </p>
<h1>Plus d'exemples</h1>
<p>Le script suivant calcul la moyenne horaire de roulement des points 'n1' et 'n2':</p>
<pre>return avg(b1.past(HOUR).average, b2.past(HOUR).average);</pre>

<p>Ce script calcule le nombre de pulsations journalière à pertir d'un compteur incrémental de pulsations (avec l'option "Start of day"):</p>
<pre>return pulse.value - pulse.ago(DAY);</pre>

<p>Le prochain script n'est pas très utile en pratique, mais il est néanmoins intéressant. Il retourne les nombres 1, 2, et 3 de façon cyclique, le changement aléatoire n'intervient qu'une fois toutes les 100 exécutions.</p>
<pre>var r = Math.random();
if (r &gt; 0.01)
    return x.value;

if (x.value == 3)
    return 1;
return x.value + 1;</pre>

<p>Ce script renvoie la somme des valeurs entières des 2 points numériques points 'r' et 't':</p>
<pre>return parseInt(t.value) + parseInt(r.value);</pre>
